package com.tanhua.dubbo.service.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.api.UserLikeApi;
import com.tanhua.dubbo.pojo.UserLike;
import com.tanhua.dubbo.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author Don
 */
@Service
public class UserLikeApiImpl implements UserLikeApi {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public static final String LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";

    public static final String NOT_LIKE_REDIS_KEY_PREFIX = "USER_NOT_LIKE_";

    @Autowired
    private UserLikeApi userLikeApi;

    /**
     * 喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean likeUser(Long userId, Long likeUserId) {
        //1.判断是否已经喜欢
        if (this.isLike(userId, likeUserId)) {
            return false;
        }
        //2.封装喜欢对象 存入mongodb
        UserLike userLike = new UserLike();
        userLike.setId(ObjectId.get());
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setCreated(System.currentTimeMillis());

        this.mongoTemplate.save(userLike);

        //3.存入redis中 减少数据库访问量
        //用户1：key -> USER_LIKE_1 , value -> 2, "1"
        //用户1：key -> USER_LIKE_1 , value -> 3, "1"
        //用户2：key -> USER_LIKE_2 , value -> 4, "1"
        String redisKey = this.getLikeRedisKey(userId);
        String hashKey = likeUserId.toString();

        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //4.判断喜欢的用户在不在不喜欢的列表里面,在则删除
        if (this.isNotLike(userId, likeUserId)) {
            redisKey = this.getNotLikeRedisKey(userId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        }
        return true;
    }

    /**
     * 不喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean notLikeUser(Long userId, Long likeUserId) {
        //1.判断用户是否已经不喜欢，如果已经不喜欢，就返回
        if (this.isNotLike(userId, likeUserId)) {
            Query query = Query.query(Criteria.where("userId").is(userId)
                    .and("likeUserId").is(likeUserId));
            this.mongoTemplate.remove(query, UserLike.class);
            return false;
        }
        //2.将用户保存到不喜欢列表中
        String redisKey = this.getNotLikeRedisKey(userId);
        String hashKey = likeUserId.toString();
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        //3.判断不喜欢的用户是否在喜欢表里,在则删除
        if (this.isLike(userId, likeUserId)) {
            // 删除redis中的数据
            redisKey = this.getLikeRedisKey(userId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
            // 删除mongodb中的数据
            Query query = Query.query(Criteria.where("userId").is(userId)
                    .and("likeUserId").is(likeUserId));
            this.mongoTemplate.remove(query, UserLike.class);
        }
        return true;
    }

    /**
     * 是否相互喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean isMutualLike(Long userId, Long likeUserId) {
        return this.isLike(userId, likeUserId) && this.isLike(likeUserId, userId);
    }

    /**
     * 查询喜欢列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> queryLikeList(Long userId) {
        // 查询redis
        String redisKey = this.getLikeRedisKey(userId);
        Set<Object> keys = redisTemplate.opsForHash().keys(redisKey);

        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }

        ArrayList<Long> list = new ArrayList<>();
        for (Object key : keys) {
            list.add(Convert.toLong(key));
        }
        return list;
    }

    /**
     * 查询不喜欢列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> queryNotLikeList(Long userId) {
        // 查询redis
        String redisKey = this.getNotLikeRedisKey(userId);
        Set<Object> keys = redisTemplate.opsForHash().keys(redisKey);

        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }

        ArrayList<Long> list = new ArrayList<>();
        for (Object key : keys) {
            list.add(Convert.toLong(key));
        }
        return list;
    }


    /**
     * 判断是否喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    public Boolean isLike(Long userId, Long likeUserId) {
        //1.查询redis判断
        String redisKey = this.getLikeRedisKey(userId);
        String hashKey = likeUserId.toString();
        if (redisTemplate.opsForHash().hasKey(redisKey, hashKey)) {
            return true;
        }
        //2.查询mongodb
        Query query = Query.query(Criteria.where("userId").is(userId)
                .and("likeUserId").is(likeUserId));
        UserLike userLike = mongoTemplate.findOne(query, UserLike.class);
        if (ObjectUtil.isEmpty(userLike)) {
            return false;
        }
        //3.存入redis
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");
        return true;
    }

    /**
     * 判断是否不喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    private Boolean isNotLike(Long userId, Long likeUserId) {
        String redisKey = this.getNotLikeRedisKey(userId);
        String hashKey = likeUserId.toString();
        return redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }

    /**
     * 获取喜欢数据的redis key
     *
     * @param userId
     * @return
     */
    private String getLikeRedisKey(Long userId) {
        return LIKE_REDIS_KEY_PREFIX + userId;
    }

    /**
     * 获取不喜欢数据的redis key
     *
     * @param userId
     * @return
     */
    private String getNotLikeRedisKey(Long userId) {
        return NOT_LIKE_REDIS_KEY_PREFIX + userId;
    }

    /**
     * 相互喜欢数
     *
     * @param userId
     * @return
     */
    @Override
    public Long queryMutualLoveCount(Long userId) {
        // 先查询我的喜欢列表
        List<Long> loveList = this.userLikeApi.queryLikeList(userId);

        // 计数变量，初始默认设置为0
        Long eachLoveCount = 0L;
        // 遍历我的喜欢列表
        for (Long loveUserId : loveList) {
            // 获取redisKey
            String redisKey = this.getLikeRedisKey(loveUserId);
            // 获取hashKey
            String hashKey = String.valueOf(userId);
            // 判断别人的喜欢列表是否有我
            if(this.redisTemplate.opsForHash().hasKey(redisKey,hashKey)){
                // 相互喜欢 计数加一
                eachLoveCount ++;
            }
        }
        return eachLoveCount;
    }

    /**
     * 喜欢数
     *
     * @param userId
     * @return
     */
    @Override
    public Long queryLoveCount(Long userId) {
        String redisKey = this.getLikeRedisKey(userId);

        return this.redisTemplate.opsForHash().size(redisKey);
    }

    /**
     * 粉丝数
     *
     * @param userId
     * @return
     */
    @Override
    public Long queryFanCount(Long userId) {
        // 在mongodb中查询喜欢过我的人
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        Long count = this.mongoTemplate.count(query, UserLike.class);
        return count;
    }

    /**
     * 相互喜欢列表
     *
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    @Override
    public PageInfo<UserLike> queryMutualLikeList(Integer page, Integer pageSize, Long userId) {
        // 查询我喜欢的列表
        List<Long> loveUserIdList = this.userLikeApi.queryLikeList(userId);

        // 查询喜欢我的列表
        Query query = Query.query(Criteria.where("userId").in(loveUserIdList).and("likeUserId").is(userId));
        return this.queryList(query,page,pageSize);
    }

    /**
     * 查询喜欢集合
     *
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    @Override
    public PageInfo<UserLike> queryLoveList(Integer page, Integer pageSize, Long userId) {
        // 查询我喜欢的
        Query query = Query.query(Criteria.where("userId").is(userId));
        return this.queryList(query,page,pageSize);
    }

    /**
     * 查询粉丝集合
     *
     * @param page
     * @param pageSize
     * @param userId
     * @return
     */
    @Override
    public PageInfo<UserLike> queryFanList(Integer page, Integer pageSize, Long userId) {
        // 查询别人喜欢我的
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        return this.queryList(query,page,pageSize);
    }


    private PageInfo<UserLike> queryList(Query query , Integer page , Integer pageSize){
        // 设置分页并按创建时间排序
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        query.with(pageRequest);
        List<UserLike> userLikeList = this.mongoTemplate.find(query, UserLike.class);


        PageInfo<UserLike> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(userLikeList);

        return pageInfo;
    }
}
